package com.atguigu.yygh.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.yygh.common.handler.YYGHException;
import com.atguigu.yygh.common.utils.HttpRequestHelper;
import com.atguigu.yygh.enums.OrderStatusEnum;
import com.atguigu.yygh.hosp.client.HospFeignClient;
import com.atguigu.yygh.model.order.OrderInfo;
import com.atguigu.yygh.model.user.Patient;
import com.atguigu.yygh.order.mapper.OrderInfoMapper;
import com.atguigu.yygh.order.service.OrderInfoService;
import com.atguigu.yygh.order.service.PaymentInfoService;
import com.atguigu.yygh.order.service.WeiPayService;
import com.atguigu.yygh.rabbitmq.constant.RabbitMQConstant;
import com.atguigu.yygh.rabbitmq.service.RabbitMQService;
import com.atguigu.yygh.user.client.PatientFeignClient;
import com.atguigu.yygh.vo.hosp.ScheduleOrderVo;
import com.atguigu.yygh.vo.msm.MsmVo;
import com.atguigu.yygh.vo.order.OrderCountQueryVo;
import com.atguigu.yygh.vo.order.OrderCountVo;
import com.atguigu.yygh.vo.order.OrderMqVo;
import com.atguigu.yygh.vo.order.OrderQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.joda.time.DateTime;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2022-11-16
 */
@Service
public class OrderInfoServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderInfoService {

    @Autowired
    private PatientFeignClient patientFeignClient;
    @Autowired
    private HospFeignClient hospFeignClient;
    @Autowired
    private RabbitMQService rabbitMQService;
    @Autowired
    private WeiPayService weiPayService;
    @Autowired
    private PaymentInfoService paymentInfoService;

    @Override
    public Long submitOrder(String scheduleId, Long patientId) {
        OrderInfo orderInfo = new OrderInfo();

        QueryWrapper<OrderInfo> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq("patient_id",patientId);
        OrderInfo orderInfo1 = baseMapper.selectOne(queryWrapper1);

        if (orderInfo1 != null){
            return orderInfo1.getId();
        }

        //获取病人信息并设置订单信息
        Patient patient = patientFeignClient.getByPatientId(patientId);
        orderInfo.setUserId(patient.getUserId());
        orderInfo.setPatientId(patient.getId());
        orderInfo.setPatientName(patient.getName());
        orderInfo.setPatientPhone(patient.getPhone());


        //获取排班信息并设置订单信息
        ScheduleOrderVo scheduleOrderVo = hospFeignClient.getScheduleOrder(scheduleId);
        BeanUtils.copyProperties(scheduleOrderVo,orderInfo);
        orderInfo.setScheduleId(scheduleOrderVo.getHosScheduleId());

        //向医院传输数据并得到返回结果
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("hoscode",scheduleOrderVo.getHoscode());
        paramMap.put("depcode",scheduleOrderVo.getDepcode());
        paramMap.put("hosScheduleId",scheduleOrderVo.getHosScheduleId());
        paramMap.put("reserveDate",new DateTime(scheduleOrderVo.getReserveDate()).toString("yyyy-MM-dd"));
        paramMap.put("reserveTime", scheduleOrderVo.getReserveTime());
        paramMap.put("amount",scheduleOrderVo.getAmount()); //挂号费用
        paramMap.put("name", patient.getName());
        paramMap.put("certificatesType",patient.getCertificatesType());
        paramMap.put("certificatesNo", patient.getCertificatesNo());
        paramMap.put("sex",patient.getSex());
        paramMap.put("birthdate", patient.getBirthdate());
        paramMap.put("phone",patient.getPhone());
        paramMap.put("isMarry", patient.getIsMarry());
        paramMap.put("provinceCode",patient.getProvinceCode());
        paramMap.put("cityCode", patient.getCityCode());
        paramMap.put("districtCode",patient.getDistrictCode());
        paramMap.put("address",patient.getAddress());
        //联系人
        paramMap.put("contactsName",patient.getContactsName());
        paramMap.put("contactsCertificatesType", patient.getContactsCertificatesType());
        paramMap.put("contactsCertificatesNo",patient.getContactsCertificatesNo());
        paramMap.put("contactsPhone",patient.getContactsPhone());
        paramMap.put("timestamp", HttpRequestHelper.getTimestamp());
        //String sign = HttpRequestHelper.getSign(paramMap, signInfoVo.getSignKey());
        paramMap.put("sign", "");

        JSONObject request = HttpRequestHelper.sendRequest(paramMap, "http://localhost:9998/order/submitOrder");

        //设置订单其他信息
        if (request.getInteger("code") == 200){
            JSONObject data = request.getJSONObject("data");
            String hosRecordId = data.getString("hosRecordId");
            Integer number = data.getInteger("number");
            String fetchTime = data.getString("fetchTime");
            String fetchAddress = data.getString("fetchAddress");

            //添加医院返回的数据
            orderInfo.setHosRecordId(hosRecordId);
            orderInfo.setNumber(number);
            orderInfo.setFetchTime(fetchTime);
            orderInfo.setFetchAddress(fetchAddress);

            //添加订单交易号
            String outTradeNo = System.currentTimeMillis() + "" + new Random().nextInt(100);
            orderInfo.setOutTradeNo(outTradeNo);
            orderInfo.setOrderStatus(OrderStatusEnum.UNPAID.getStatus());

            //保存订单信息
            baseMapper.insert(orderInfo);

            //TODO 更新可预约数和剩余可预约数
            Integer availableNumber = data.getInteger("availableNumber");

            OrderMqVo orderMqVo = new OrderMqVo();
            orderMqVo.setAvailableNumber(availableNumber);
            orderMqVo.setScheduleId(scheduleId);

            //TODO 给就诊人发信息
            MsmVo msmVo = new MsmVo();
            msmVo.setPhone(patient.getPhone());
            msmVo.setTemplateCode("SMS_247905059");
            msmVo.setParam(null);
            orderMqVo.setMsmVo(msmVo);

            rabbitMQService.sendMessage(RabbitMQConstant.EXCHANGE_DIRECT_ORDER,RabbitMQConstant.ROUTING_ORDER,orderMqVo);


            //返回订单id
            return orderInfo.getId();
        }else {
            throw new YYGHException(20001,"提交订单失败!");
        }
    }

    @Override
    public Page<OrderInfo> getPageList(Integer pageNum, Integer pageSize, Long userId, OrderQueryVo orderQueryVo) {
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("user_id",userId);
        if (!StringUtils.isEmpty(orderQueryVo.getPatientId())){
            queryWrapper.eq("patient_id",orderQueryVo.getPatientId());
        }
        if (!StringUtils.isEmpty(orderQueryVo.getOrderStatus())){
            queryWrapper.eq("order_status",orderQueryVo.getOrderStatus());
        }
        Page<OrderInfo> page = new Page<>(pageNum,pageSize);
        Page<OrderInfo> orderInfoPage = baseMapper.selectPage(page, queryWrapper);
        for (OrderInfo record : orderInfoPage.getRecords()) {
            this.packOrderStatus(record);
        }

        return page;
    }

    private void packOrderStatus(OrderInfo orderInfo){
        Map<String,Object> map = new HashMap<>();
        map.put("orderStatusString",OrderStatusEnum.getStatusNameByStatus(orderInfo.getOrderStatus()));
        orderInfo.setParam(map);
    }

    @Override
    public List<Map<String, Object>> statusList() {
        List<Map<String, Object>> statusList = OrderStatusEnum.getStatusList();
        return statusList;
    }

    @Override
    public OrderInfo getOrders(Long orderId) {
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        this.packOrderStatus(orderInfo);
        return orderInfo;
    }

    @Override
    public void updateStatus(OrderStatusEnum paid, Long orderId) {
        UpdateWrapper<OrderInfo> updateWrapper = new UpdateWrapper<>();
        updateWrapper.eq("id",orderId);
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setOrderStatus(paid.getStatus());

        baseMapper.update(orderInfo,updateWrapper);
    }

    @Transactional
    @Override
    public void cancelOrder(Long orderId) {
        //判断订单是否在取消预约范围内
        OrderInfo orderInfo = baseMapper.selectById(orderId);
        if (new DateTime(orderInfo.getQuitTime()).isBeforeNow()){
            throw new YYGHException(20001,"超过退号截止时间!");
        }
        //给第三方医院发请求
        Map<String,Object> map = new HashMap<>();
        map.put("hoscode",orderInfo.getHoscode());
        map.put("hosRecordId",orderInfo.getHosRecordId());

        JSONObject response = HttpRequestHelper.sendRequest(map, "http://localhost:9998/order/updateCancelStatus");

        if (response == null || response.getIntValue("code") != 200){
            throw new YYGHException(20001,"退号失败!");
        }
        //判断订单是否支付
        if (orderInfo.getOrderStatus().intValue() == OrderStatusEnum.PAID.getStatus().intValue()){
            //退钱
            Boolean flag = weiPayService.refund(orderId);
            if (!flag){
                throw new YYGHException(20001,"退款失败!");
            }
        }
        //修改表信息
        orderInfo.setOrderStatus(OrderStatusEnum.CANCLE.getStatus());
        baseMapper.updateById(orderInfo);

        paymentInfoService.updatePaymentStatus(orderId);
        //修改可预约数
        OrderMqVo orderMqVo = new OrderMqVo();
        orderMqVo.setScheduleId(orderInfo.getHoscode() + " " + orderInfo.getDepcode() + " " + orderInfo.getScheduleId());
        //给就诊人发短信
        MsmVo msmVo = new MsmVo();
        msmVo.setPhone("15290291625");
        orderMqVo.setMsmVo(msmVo);

        rabbitMQService.sendMessage(RabbitMQConstant.EXCHANGE_DIRECT_ORDER,RabbitMQConstant.ROUTING_ORDER,orderMqVo);
    }

    @Override
    public List<OrderInfo> getRemindPatient() {
        QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("reserve_date",new DateTime(new Date()).toString("yyyy-MM-dd"));
        queryWrapper.ne("order_status",OrderStatusEnum.CANCLE.getStatus());
        List<OrderInfo> orderInfoList = baseMapper.selectList(queryWrapper);
        return orderInfoList;
    }

    @Override
    public Map<String, Object> getCountMap(OrderCountQueryVo orderCountQueryVo) {
        Map<String,Object> map = new HashMap<>();
        List<OrderCountVo> orderCountVoList = baseMapper.getCountList(orderCountQueryVo);
        List<String> dateList = orderCountVoList.stream().map(OrderCountVo::getReserveDate).collect(Collectors.toList());
        List<Integer> countList = orderCountVoList.stream().map(OrderCountVo::getCount).collect(Collectors.toList());
        map.put("dateList",dateList);
        map.put("countList",countList);
        return map;
    }
}
